package com.spring.mvc.http.util;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.spring.mvc.util.StringUtil;

public class HttpUtil {
	
	private static final Logger logger=LoggerFactory.getLogger(HttpUtil.class);
	
	/**
	 * 定义编码格式（UTF-8）
	 */
	public static final String URL_PARAM_ENCODECHARSET_UTF8="UTF-8";
	
	/**
	 * 定义编码格式（GBK）
	 */
	public static final String URL_PARAM_ENCODECHARSET_GBK="GBK";
	
	/**
	 * url地址参数分隔符
	 */
	private static final String URL_PARAM_CONNECT_FLAG="&";
	
	/**
	 * 初始化字符串为""
	 */
	private static final String EMPTY="";
	
	/**
	 * 初始化httpClient
	 */
	private static MultiThreadedHttpConnectionManager connectionManager =null;
	
	private static int connectionTimeOut = 25000;
	
	private static int socketTimeOut = 25000;
	
	private static int maxConnectionPerHost = 20; 
	
	private static int maxTotalConnections = 20;
	
	private static HttpClient client;
	
	static{  
        connectionManager = new MultiThreadedHttpConnectionManager();  
        connectionManager.getParams().setConnectionTimeout(connectionTimeOut);  
        connectionManager.getParams().setSoTimeout(socketTimeOut);  
        connectionManager.getParams().setDefaultMaxConnectionsPerHost(maxConnectionPerHost);  
        connectionManager.getParams().setMaxTotalConnections(maxTotalConnections);  
        client = new HttpClient(connectionManager);  
    }
	

	/**
	 * 获取IP地址
	 * @param request
	 * @return
	 */
	public static String getIpAddr(HttpServletRequest request) {  
	    String ip = request.getHeader("x-forwarded-for");  
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
	        ip = request.getHeader("Proxy-Client-IP");  
	    }  
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
	        ip = request.getHeader("WL-Proxy-Client-IP");  
	    }  
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
	        ip = request.getRemoteAddr();  
	    }  
	    return ip;  
	}
	
	/**
	 * 检查验证码是否正确
	 * @param request
	 * @param check
	 * @return
	 */
	public static boolean isCheckCode(HttpServletRequest request,String check){
		String code=(String)request.getSession().getAttribute("KAPTCHA_SESSION_KEY");
		if(StringUtil.isNotEmpty(code) && StringUtil.isNotEmpty(check) && code.equals(check)){
			return true;
		}
		return false;
	}
	
	/**
	 * 以http方式从指定url下载文件
	 * @param url 请求url 路径结束带'/'
	 * @param localAddr 文件保存本地地址 路径结束带'/'
	 */
	public static void downLoad(String url,String localAddr,String fileName){
		GetMethod method=null;
		InputStream is=null;
		FileOutputStream fos=null;
		try {
			method=new GetMethod(url+fileName);
			method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, 
					new DefaultHttpMethodRetryHandler());
			client.executeMethod(method);
			is=method.getResponseBodyAsStream();
			fos=new FileOutputStream(localAddr+fileName);
			byte[] buffer=new byte[1024];
			int len=0;
			while((len=is.read(buffer))!=-1){
				fos.write(buffer,0,len);
			}
		} catch (HttpException e) {
			logger.error("Please check your provided http address! url:"+url,e);
		} catch (IOException e) {
			logger.error("Please check your network",e);
		} finally{
			try {
				if(null != is )
					is.close();
				if(null != fos)
					fos.close();
				if(null != method)
					method.releaseConnection();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * POST 方式提交数据
	 * @param url
	 * @param param
	 * @param enc
	 * @return
	 */
	public static String URLPost(String url,Map<String, String> param,String enc){
		String response=EMPTY;
		PostMethod postMethod=null;
		try {
			postMethod=new PostMethod(url);
			postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, 
					new DefaultHttpMethodRetryHandler());
			postMethod.setRequestHeader("Content-type","application/x-www-form-urlencoded;charset="+enc);
			Set<String> keySet=param.keySet();
			for(String key:keySet){
				String value=param.get(key);
				postMethod.addParameter(key, value);
			}
			int statusCode=client.executeMethod(postMethod);
			if(statusCode==HttpStatus.SC_OK){
				response=postMethod.getResponseBodyAsString();
			}else{
				logger.error("status code:"+postMethod.getStatusCode());
			}
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (HttpException e) {
			logger.error("Please check your provided http address! url:"+url,e);
		} catch (IOException e) {
			logger.error("Please check your network!",e);
		} finally{
			if(null != postMethod){
				postMethod.releaseConnection();
				postMethod=null;
			}
		}
		return response;
	}
	
	/**
	 * Get 方式提交数据
	 * @param url
	 * @param param
	 * @param enc
	 * @return
	 */
	public static String URLGet(String url,Map<String, String> param,String enc){
		String response=EMPTY;
		GetMethod getMethod=null;
		StringBuffer strtTotalURL=new StringBuffer(EMPTY);
		
		if(strtTotalURL.indexOf("?")==-1){
			strtTotalURL.append(url).append("?").append(getUrl(param,enc));
		}else{
			strtTotalURL.append(url).append(URL_PARAM_CONNECT_FLAG).append(getUrl(param, enc));
		}
		logger.debug("Get request URL=\n"+strtTotalURL.toString());
		
		try {
			getMethod=new GetMethod(url);
			//使用系统提供的默认的恢复策略
			getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
				    new DefaultHttpMethodRetryHandler());
			getMethod.setRequestHeader("Content-type","application/x-www-form-urlencoded;charset="+enc);
			int statusCode=client.executeMethod(getMethod);
			if(statusCode==HttpStatus.SC_OK){
				response=getMethod.getResponseBodyAsString();
			}else{
				logger.debug("status code："+getMethod.getStatusCode());
			}
		} catch (HttpException e) {
			logger.error("Please check your provided http address! url:"+url,e);
		} catch (IOException e) {
			logger.error("Please check your network!",e);
		} finally{
			if(null != getMethod){
				getMethod.releaseConnection();
				getMethod=null;
			}
		}
		return response;
	}
	
	/**
	 * 根据Map生成Url参数字符串
	 * @param param
	 * @param enc
	 * @return
	 */
	public static String getUrl(Map<String, String> param,String enc){
		if(null == param || param.keySet().size() == 0 ){
			return EMPTY;
		}
		StringBuilder url=new StringBuilder();
		Set<String> keys=param.keySet();
		for(Iterator<String> it=keys.iterator();it.hasNext();){
			String key=it.next();
			if(param.containsKey(key)){
				String val=param.get(key);
				String str=val!=null?val:EMPTY;
				try{
					str=URLEncoder.encode(str,enc);
				}catch(UnsupportedEncodingException e){
					e.printStackTrace();
				}
				url.append(key).append("=").append(str).append(URL_PARAM_CONNECT_FLAG);
			}
		}
		String strURL=EMPTY;
		strURL=url.toString();
		if(strURL.endsWith(URL_PARAM_CONNECT_FLAG)){
			strURL=strURL.substring(0, strURL.length()-1);
		}
		return strURL;
	}
	
	public static void main(String[] args) {
		Map<String, String > param= new HashMap<String, String>();
		param.put("hl", "zh-CN");
		param.put("newwindow", "1");
		param.put("safe", "strict");
		param.put("tbo", "d");
		param.put("site", "");
		param.put("source", "hp");
		param.put("q", "hello");
		param.put("btnK", "Google+搜索");
		String content=URLGet("http://www.google.com.hk/search", param, URL_PARAM_ENCODECHARSET_UTF8);
		System.out.println(content);
	}
}
